<?php
namespace PsiFramework\Classes\Model;

use PsiFramework\Plugins\Shop\Classes\Model\OrderItemLinkTax;

import("Classes.Util.Log.Logger");
import("Classes.Model.Object");

use \PsiFramework\Classes\DAO\DAOInterface\IDAO;
use \PsiFramework\Classes\Model\Object;
use \PsiFramework\Classes\Util\Log\Logger;

/**
 * PsiFramework
 * Php Simple Framework
 *
 * @author Rémi San
 * @version beta
 */

/**
 * Objet Proxy class
 *
 * @package Model
 */
class ObjectProxy extends Object
{

    protected /*Object*/  $_object ;
    protected /*IDAO*/    $_dao ;
    protected /*array*/   $_retrieved ;
    protected /*array*/   $_lazyIds ;
    protected /*boolean*/ $_checkSecurity ;

    protected /*Logger*/  $_logger ;


    public function __construct(Object $object, IDAO $dao)
    {
        $this->_object = $object ;
        $this->_dao = $dao ;

        $this->_checkSecurity = true;
        
        $this->_retrieved = array();
        $this->_lazyIds = array();

        $this->_logger = new Logger(get_class($object));
    }

    public function getId()
    {
        return $this->_object->getId();
    }
    
    public function getClassName()
    {
    	return get_class($this->_object);
    }

    public function toString()
    {
        return $this->_object->toString();
    }

    public function setCheckSecurity(/*boolean*/ $checkSecurity)
    {
        $this->_checkSecurity = $checkSecurity;
    }
    
    protected function setLazyId($varName, $id)
    {
        $this->_lazyIds[$varName] = $id ;
    }

    protected function getLazyId($varName)
    {
        if (isset($this->_lazyIds[$varName])) {
            return $this->_lazyIds[$varName] ;
        } else {
            return null ;
        }
    }

    public function setRetrieved($varName)
    {
        $this->_retrieved[$varName] = true ;
    }

    protected function isRetrieved($varName)
    {
        if (isset($this->_retrieved[$varName])
            && $this->_retrieved[$varName]
        ) {
            return true ;
        } else {
            return false ;
        }
    }

    public function __call($method, $args)
    {
        $return = null ;
        if (startsWith($method, 'lazyset')) {
            $varName = lcfirst(substr($method, 7));
            
            $this->_logger->debug(
                "Set lazy id for " .
                get_class($this->_object) .
                "[". $this->_object->getId() ."]->" .
                $varName
            );
            
            $this->setLazyId($varName, $args[0]);
        } else {
            $return = call_user_func_array(
                array($this->_object,$method),
                $args
            );

            if (is_null($return) && startsWith($method, 'get')) {
                $varName = lcfirst(substr($method, 3));
                if (!$this->isRetrieved($varName)) {
                    $lazyId = $this->getLazyId($varName);
                    if (!is_null($lazyId)) {
                        $params
                            = $this->_dao->getObjectParameters()->getParameter(
                                $varName
                            );
                        if (!is_null($params)
                            && !$params->isPrimitive()
                            && !$params->isPrimitiveObject()
                        ) {
                            $this->_logger->debug(
                                "Lazy Initialisation for " .
                                get_class($this->_object) .
                                "[". $this->_object->getId() ."]->" .
                                $varName
                            );
                            
                            $this->_dao->addLinkedObject(
                                $this,
                                $params,
                                $lazyId,
                                $this->_checkSecurity
                            );
                            
                            $return = $this->_object->{$params->getter}() ;
                        }
                    }
                }
            }
        }

        return $return ;
    }
}
